package com.ultrapower.util.topology;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class TimeWindow implements Iterable<Long> {
	private final long windowSlotSize;

	private final long from;
	private final long to;

	private long windowFrom;
	private long windowTo;

	public TimeWindow(long from ,long to) {
		this(from,to, TimeWindowSampler.SAMPLER);
	}

	public TimeWindow(long from ,long to, TimeWindowSampler sampler) {
		if (sampler == null) {
			throw new NullPointerException("sampler must not be null");
		}
		this.windowSlotSize = sampler.getWindowSize(from , to);
		this.from=from;
		this.to=to;
		this.windowFrom = refineTimestamp(from);
		this.windowTo = refineTimestamp(to);
	}

	public Iterator<Long> iterator() {
		return new Itr();
	}

	/**
	 * converts the timestamp to the matching window slot's reference timestamp
	 * 
	 * @param timestamp
	 * @return
	 */
	public long refineTimestamp(long timestamp) {
		long time = (timestamp / windowSlotSize) * windowSlotSize;
		return time;
	}


	public long getWindowSlotSize() {
		return windowSlotSize;
	}

	public long getWindowRangeCount() {
		return (getWindowRange() / windowSlotSize) + 1;
	}


	public int getWindowIndex(long time) {
		long index = (time - windowFrom) / this.windowSlotSize;
		return (int) index;
	}

	private class Itr implements Iterator<Long> {

		private long cursor;

		public Itr() {
			this.cursor = windowFrom;
		}

		@Override
		public boolean hasNext() {
			if (cursor > windowTo) {
				return false;
			}
			return true;
		}

		@Override
		public Long next() {
			long current = cursor;
			if (hasNext()) {
				cursor += windowSlotSize;
				return current;
			}
			throw new NoSuchElementException();
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
	 public long getWindowRange() {
	        return windowTo - windowFrom;
	    }
}
